package fr.vahren.dotastrat.game.command;

import java.util.Arrays;
import java.util.List;

import fr.vahren.dotastrat.game.D2SMessageType;
import fr.vahren.dotastrat.model.D2SHeroUnit;
import fr.vahren.dotastrat.model.D2SMap;
import fr.vahren.dotastrat.model.D2SPlayer;
import fr.vahren.dotastrat.model.D2SUnit;

public class D2SAttackCommand extends D2SCommand {

	public D2SAttackCommand(D2SPlayer player, D2SMap map, D2SHeroUnit hero,
			List<D2SUnit> targetUnit) {
		super(null, player, hero, map, targetUnit, null, null);
		priority = unit.isMelee() ? 1 : 3;// melee is prio 1, range is 3.
		range = unit.getAttackRange();
	}

	@Override
	public void execute() {
		for (D2SUnit target : targetUnits) {
			if (target.isMoving()) {
				// EVASION!
				// compute speed delta
				int speedDelta = target.getSpeed() - unitSnapshot.getSpeed();

				if (unitSnapshot.isMelee()) {
					if (speedDelta < 1) {
						applyAttackDamage(unitSnapshot, target, false, unit);
					} else {// else damage avoided
						sendAttackMessage(target, target.getName() + " evaded "
								+ unit.getName() + "'s attack entirely");
					}
				} else {
					// ranged
					if (speedDelta == 1) {
						// half attacks
						sendAttackMessage(target, target.getName() + " evades "
								+ unit.getName() + "'s attack partially");
						applyAttackDamage(unitSnapshot, target, false, unit);
					} else if (speedDelta < 1) {
						applyAttackDamage(unitSnapshot, target, false, unit);
					}// else damage avoided
				}
			} else {
				// just apply damage
				applyAttackDamage(unitSnapshot, target, false, unit);
			}

		}
	}

	private void sendAttackMessage(D2SUnit target, String message) {
		game.sendToAnyoneThatCanSee(target.getId(),
				Arrays.asList(game.getMap().getZoneFromHero(target.getId())),
				player.getSide(), message, D2SMessageType.ATTACK);
	}

	private void applyAttackDamage(D2SHeroUnit unitSnapshot,
			D2SUnit target, boolean reduced, D2SHeroUnit unit) {
		if (map.isRangeOk(unit, target, range)) { // or any other verification
			unitSnapshot.applyAttackDamage(target, reduced, unit);
			// attack has been applied, so the unit is a valid attacker
			target.addAttacker(unit.getId());
		}
	}

}
